#pragma once

#include <windows.h>		// Header File For Windows
#include <stdio.h>			// Header File For Standard Input/Output
#include <gl\gl.h>			// Header File For The OpenGL32 Library
#include <gl\glu.h>			// Header File For The GLu32 Library
//#include <gl\glut.h>
#include <gl\glaux.h>		// Header File For The Glaux Library
#include <iostream>

#include "picture.h"
#include "vector3d.h"

using namespace System::Windows::Forms;

namespace OpenGLForm 
{
	public ref class COpenGL: public System::Windows::Forms::NativeWindow
	{
	public:

		public:
		HDC m_hDC;
		HWND		hWnd;		// Holds Our Window Hand
		HGLRC m_hglrc;
		GLfloat	rtri;				// Angle for the triangle
		GLfloat	rquad;				// Angle for the quad
		picture* pic;
		Vector3d* Position;
		Vector3d* ViewDir;
		Vector3d* RightVector;
		Vector3d* UpVector;
			
		COpenGL(System::Windows::Forms::Form ^ parentForm, GLsizei iWidth, GLsizei iHeight)
		{
			CreateParams^ cp = gcnew CreateParams;

			// Set the position on the form
			cp->X = 10;
			cp->Y = 400;
			cp->Height = iHeight;
			cp->Width = iWidth;

			// Specify the form as the parent.
			cp->Parent = parentForm->Handle;

			// Create as a child of the specified parent and make OpenGL compliant (no clipping)
			cp->Style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

			// Create the actual window
			this->CreateHandle(cp);

			m_hDC = GetDC((HWND)this->Handle.ToPointer());
			
			if(m_hDC)
			{
				std::ofstream myfile;
				 myfile.open("done2.txt", std::ios::app);
				 myfile << "CONSRUCTOR\n";
			     myfile.close();

				MySetPixelFormat(m_hDC);
				ReSizeGLScene(iWidth, iHeight);
				pic = new picture();
				InitGL(iWidth, iHeight);
			}

			
		}

		// Doubles as MoveBackWard with negative Distance
	void MoveForward(GLfloat Distance)
	{
		std::ofstream myfile;

		Vector3d MoveVector = Vector3d(0.0,0.0,0.0);
		MoveVector.x = ViewDir->x * -Distance;
		MoveVector.y = ViewDir->y * -Distance;
		MoveVector.z = ViewDir->z * -Distance;
		*Position = Position->add(MoveVector);
		myfile.open("done2.txt", std::ios::app);
		myfile << "x = " << Position->x << "\n";
		myfile << "y = " << Position->y << "\n";
		myfile << "z = " << Position->z << "\n";
		myfile.close();
	}

	// Doubles as MoveLeft with negative Distance
	void MoveRight(GLfloat Distance)
	{
		std::ofstream myfile;
		Vector3d MoveVector;
		MoveVector.z = -ViewDir->x * -Distance;
		MoveVector.y = 0.0;
		MoveVector.x = ViewDir->z * -Distance;
		*Position = Position->add(MoveVector);
		myfile.open("done2.txt", std::ios::app);
		myfile << "x = " << Position->x << "\n";
		myfile << "y = " << Position->y << "\n";
		myfile << "z = " << Position->z << "\n";
		myfile.close();
	}

		//Draw all the time
		System::Void Render(System::Void)
		{
			std::ofstream myfile;
			myfile.open("done2.txt", std::ios::app);
	    	myfile << "RENDERING\n";
	        myfile.close();

			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// Clear The Screen And The Depth Buffer
			glLoadIdentity();										// Reset The View
			glTranslatef(0.0f,0.0f,-5.0f);
			glTranslatef( -Position->x, -Position->y, -Position->z );
			
			pic->LoadGLTextures();
			pic->DrawGLScene();
		}

		System::Void SwapOpenGLBuffers(System::Void)
		{
			SwapBuffers(m_hDC);
		}

	
	protected:
		~COpenGL(System::Void)
		{
			this->DestroyHandle();
		}

		GLint MySetPixelFormat(HDC hdc)
		{
			static	PIXELFORMATDESCRIPTOR pfd=				// pfd Tells Windows How We Want Things To Be
				{
					sizeof(PIXELFORMATDESCRIPTOR),				// Size Of This Pixel Format Descriptor
					1,											// Version Number
					PFD_DRAW_TO_WINDOW |						// Format Must Support Window
					PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL
					PFD_DOUBLEBUFFER,							// Must Support Double Buffering
					PFD_TYPE_RGBA,								// Request An RGBA Format
					16,										// Select Our Color Depth
					0, 0, 0, 0, 0, 0,							// Color Bits Ignored
					0,											// No Alpha Buffer
					0,											// Shift Bit Ignored
					0,											// No Accumulation Buffer
					0, 0, 0, 0,									// Accumulation Bits Ignored
					16,											// 16Bit Z-Buffer (Depth Buffer)  
					0,											// No Stencil Buffer
					0,											// No Auxiliary Buffer
					PFD_MAIN_PLANE,								// Main Drawing Layer
					0,											// Reserved
					0, 0, 0										// Layer Masks Ignored
				};
			
			GLint  iPixelFormat; 
		 
			// get the device context's best, available pixel format match 
			if((iPixelFormat = ChoosePixelFormat(hdc, &pfd)) == 0)
			{
				MessageBox::Show("ChoosePixelFormat Failed");
				return 0;
			}
			 
			// make that match the device context's current pixel format 
			if(SetPixelFormat(hdc, iPixelFormat, &pfd) == FALSE)
			{
				MessageBox::Show("SetPixelFormat Failed");
				return 0;
			}

			if((m_hglrc = wglCreateContext(m_hDC)) == NULL)
			{
				MessageBox::Show("wglCreateContext Failed");
				return 0;
			}

			if((wglMakeCurrent(m_hDC, m_hglrc)) == NULL)
			{
				MessageBox::Show("wglMakeCurrent Failed");
				return 0;
			}


			return 1;
		}
		
		//Intialisation for GL
		GLvoid InitGL(GLsizei Width, GLsizei Height)	// This Will Be Called Right After The GL Window Is Created
		{
			Position = new Vector3d(0.0,0.0,0.0);
			ViewDir = new Vector3d(0.0,0.0,-1.0);
			RightVector = new Vector3d(1.0,0.0,0.0);
			UpVector = new Vector3d(0.0,1.0,0.0);

			std::ofstream myfile;
			 myfile.open("done2.txt", std::ios::app);
			 myfile << "INITGL\n";
		     myfile.close();
		

			pic->LoadGLTextures();							// Load The Texture(s)
			glEnable(GL_TEXTURE_2D);					// Enable Texture Mapping

			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);		// This Will Clear The Background Color To Black
			glClearDepth(1.0);							// Enables Clearing Of The Depth Buffer
			glDepthFunc(GL_LESS);						// The Type Of Depth Test To Do
			glEnable(GL_DEPTH_TEST);					// Enables Depth Testing
			glShadeModel(GL_SMOOTH);					// Enables Smooth Color Shading

			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();							// Reset The Projection Matrix

			gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);	// Calculate The Aspect Ratio Of The Window

			glMatrixMode(GL_MODELVIEW);

			 myfile.open("done2.txt", std::ios::app);
			 myfile << "Done init\n";
		     myfile.close();
		}

		//On resize
		GLvoid ReSizeGLScene(GLsizei width, GLsizei height)		// Resize and initialise the gl window
		{
			if(height==0){ height=1;}									// Prevent A Divide By Zero By
												// Making Height Equal One
			glViewport(0,0,width,height);						// Reset The Current Viewport

			glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
			glLoadIdentity();									// Reset The Projection Matrix

			// Calculate The Aspect Ratio Of The Window
			gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

			glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
			glLoadIdentity();									// Reset The Modelview Matrix
		}
	};
}